/**
 * Description: 服务端 
 * File: server.c |Time: 2021-06-28 04:40
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "staff.h"
#include "server.h"

//允许监听套接字的个数（一般设置成5或10）
#define LISTEN_BACKLOG 10
extern char username[BUFSIZE];

int main(int argc, const char *argv[])
{
	//中端输入ip地址，端口号
    if (argc < 3) {
        printf("Usage: %s <ip> <port>\n", argv[0]);
        return EXIT_FAILURE;
    }
	
    int res;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    const char *ip = argv[1];
    const int port = atoi(argv[2]);

    int is_reuse = 1;
    
	//设置端口复用
	res = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &is_reuse, sizeof(is_reuse));
    if (res < 0) {
        ERR("setsockopt error");
    }
	
	//填充网络信息结构体
    struct sockaddr_in serveraddr;
    socklen_t addrlen = sizeof(serveraddr);
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    serveraddr.sin_addr.s_addr = inet_addr(ip);
    
	//将套接字与网络信息结构体进行绑定
    res = bind(sockfd, (struct sockaddr *)&serveraddr, addrlen);
    if (res < 0) 
    {
        ERR("bind error");
    }
	
	//将套接字设置成被动监听状态
    res = listen(sockfd, LISTEN_BACKLOG);
    if (res < 0) {
        ERR("listen error");
    }

    int recvfd;
    pid_t pid;
    msg_t msg;

    // 创建数据库与表
    sqlite3 *db = db_create();
    db_staff_create(db);
    db_history_create(db);

    int check_number(sqlite3 *db,char *sql);
    int staff_no = check_number(db, "select * from staff where 1");
    if (staff_no == 0) 
    {
        // 添加测试数据
        staff_info_t test[3] = {
            {1001, 2, "admin", "admin", 23, "13122223333", "addr01", "20210102", 2, "position01", 1200.2},
            {1002, 2, "user02", "passwd02", 24, "13122223334", "addr02", "20210103", 3, "position02", 1201.2},
            {1003, 1, "user03", "passwd03", 25, "13122223335", "addr03", "20210104", 4, "position03", 1203.2}
        };
        int i = 0;
        for (i = 0; i < 3; i++) 
        {
            db_insert(db,test[i]);
        }
    }
    
    db_close(db);

 

	//实现与客户端交互的逻辑
    while(1) {
	
		//连接监听的套接字中的第一个客户端连接请求
        recvfd = accept(sockfd, (struct sockaddr *)&serveraddr, &addrlen);
        if (recvfd < 0) {
            ERR("acccpt error");
        }
        printf("connected.\n");

		//创建多进程，实现多进程并发
        pid = fork();
        if (pid < 0) {
            ERR("pid error");
        }

        if (pid > 0) {
			
			//接收客户端发来的信息
            while(1) {
				//清空缓冲区
                memset(&msg, 0, sizeof(msg));
                res = recv(recvfd, &msg, sizeof(msg), 0);
                if (res == 0) 
                {
                    if (strlen(username) > 0) 
                    {
                        char history_desc[BUFSIZE];
                        sprintf(history_desc, "登陆");
                        add_history(history_desc);
                        printf("登陆添加历史记录\n");
                    }

                   printf("client exit\n");
                    exit(EXIT_SUCCESS);
                    break;
                }

                if(res < 0) {
                    ERR("recv error");
                }

                switch (msg.type) {
                    case TYPE_USER_LOGIN:
                        login(recvfd, TYPE_USER_LOGIN, msg);
                        break;
                    case TYPE_ADMIN_LOGIN:
                        login(recvfd, TYPE_ADMIN_LOGIN, msg);
                        break;
                    case TYPE_ADD:
                        add(recvfd, msg);
                        break;
                    case TYPE_ADMIN_SEARCH:
                        if (strlen(msg.staff_info.name) == 0) {
                            printf("查询所有员工信息\n");
                            all(recvfd);
                        }

                        if (msg.staff_info.no > 0) {
                            search_by_no(recvfd, msg);
                        }
                        break;
                    case TYPE_DELETE:
                        del(recvfd, msg);
                        break;
                    case TYPE_ADMIN_MODIFY:
                        modify(recvfd, msg);
                        break;
                    case TYPE_HISTORY:
                        printf("添加历史记录\n");
                        history(recvfd);
                        break;
                    default:
                        break;
                }
            }
            
        }
    }
    
    return 0;
}

